import React, { Component } from "react";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import Stats from "three/examples/jsm/libs/stats.module";
import URDFLoader from "urdf-loader";

export default
class AppRenderer extends Component {
  constructor(props) {
    super(props);

    this.initGraphics = this.initGraphics.bind(this);
    this.animate = this.animate.bind(this);
    this.onWindowResize = this.onWindowResize.bind(this);

    this.refContainer = React.createRef();
    this.refStats = React.createRef();
  }

  componentDidMount() {

    this.initGraphics();
    // this.initScene();
    // this.addTestObject();
    this.animate();

    window.addEventListener( 'resize', this.onWindowResize, true );
  }

  componentWillUnmount() {
    
    if( this.renderer ) {
      this.renderer.forceContextLoss();
      this.renderer.dispose();
    }
    
    //todo: 清理资源
    if( this.scene ) {
      const children = this.scene.children;
      for( var i = 0, il = children.length; i < il; i++ ) {
        this.scene.remove(children[i]);
      }
    }

    if( this.requestID ) {
      window.cancelAnimationFrame( this.requestID );
    }

    window.removeEventListener( 'resize', this.onWindowResize, true);
  }

  initGraphics() {
    console.log(">> 初始化渲染器...");
    const container = this.refContainer.current;
    const divStats = this.refStats.current;
    
    if( !container ) return;
    container.innerHTML = "";

    const renderer = new THREE.WebGLRenderer();
    renderer.setPixelRatio( container.devicePixelRatio );
    renderer.setSize( container.clientWidth, container.clientHeight );
    // renderer.shadowMap.enabled = true;

    const camera = new THREE.PerspectiveCamera( 60, container.clientWidth / container.clientHeight, 0.2, 2000 );
    camera.position.set(0, 2, 2);

    const controls = new OrbitControls( camera, renderer.domElement);
    controls.target.set( 0, 0, 0 );

    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0xffffff);

    const ambientLight = new THREE.AmbientLight( 0xffffff, 5 );
    scene.add( ambientLight );

    // grid
    const gridHelper = new THREE.GridHelper();
    scene.add( gridHelper );

    // 渲染到窗口
    renderer.domElement.style.zIndex = -1;
    container.appendChild( renderer.domElement );

    const stats = new Stats();
    // stats.domElement.style.position = 'absulote';
    // stats.domElement.style.top = '2px';
    // stats.domElement.style.left = '2px';
    divStats.appendChild( stats.domElement );

    const clock = new THREE.Clock();
    
    this.renderer = renderer;
    this.scene = scene;
    this.camera = camera;
    this.controls = controls;
    this.stats = stats;
    this.clock = clock;

    if( this.props.UpdateScene ) {
      this.props.UpdateScene( scene );
    }

  }

  onWindowResize() {

    const container = this.refContainer.current;

    if( !container ) return;

    this.camera.aspect = container.clientWidth / container.clientHeight;
    this.camera.updateProjectionMatrix();

    this.renderer.setPixelRatio( container.devicePixelRatio );
    this.renderer.setSize( container.clientWidth, container.clientHeight );
  }

  animate() {
    this.requestID = requestAnimationFrame( this.animate ); 
    let dt = this.clock.getDelta();
    
    if( this.stats ){
      this.stats.update();
    }
    this.controls.update( dt );
    this.renderer.render( this.scene, this.camera ); 
  }

  render() {
    const settings = this.props.Settings;
    return(
      <>
      <div ref={this.refContainer} className="container">
        {"渲染容器"}
      </div>
      <div ref={this.refStats} className={settings.enableStats?"":'hidden'}></div>
      </>
    )
  }
}

// 加载URDF文件到场景
function loadURDFRobot( scene, urdf, done ) {

  const manager = new THREE.LoadingManager();
  const loader = new URDFLoader( manager );

  var packages = {};
  var url = "";
  
  switch( urdf.id ) {
    case 'UR5':
      packages = { ur_description : '/robots/ur_description' };
      url = "/robots/ur_description/urdf/ur5_robot.urdf";
      break;
    default:
      return;
  }

  loader.packages = packages;
  loader.load(
    url,                    // The path to the URDF within the package OR absolute
    robot => {
      console.log(">>load robot done...")
      // The robot is loaded!
      scene.add( robot );
      
      if( urdf.xyz ) {
        robot.position.set(urdf.xyz[0],urdf.xyz[1],urdf.xyz[2]);
      }
      if( urdf.rpy ){
        robot.setRotationFromEuler(new THREE.Euler(urdf.rpy[0], urdf.rpy[1], urdf.rpy[2]));
      }

      if( done ) {
        done( robot );
      }

    }
  );
}

export {
  loadURDFRobot,
}